package com.monkey.serviceprice.service;

import com.monkey.internalcommon.constant.CommonStatusEnum;
import com.monkey.internalcommon.dto.PriceRule;
import com.monkey.internalcommon.dto.ResponseResult;
import com.monkey.internalcommon.request.ForecastPriceDTO;
import com.monkey.internalcommon.response.DirectionResponse;
import com.monkey.internalcommon.response.ForecastPriceResponse;
import com.monkey.internalcommon.util.BigDecimalUtils;
import com.monkey.serviceprice.mapper.PriceRuleMapper;
import com.monkey.serviceprice.remote.ServiceMapClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author tao
 * @date 2022/6/25 09:18
 */
@Service
@Slf4j
public class ForecastPriceService {

    @Autowired
    private ServiceMapClient serviceMapClient;

    @Autowired
    private PriceRuleMapper priceRuleMapper;

    /**
     * 根据 出发地和目的地经纬度 计算预估价格
     * @param depLongitude
     * @param depLatitude
     * @param destLongitude
     * @param destLatitude
     * @return
     */
    public ResponseResult forecastPrice(String depLongitude, String depLatitude, String destLongitude, String destLatitude) {

        log.info("出发地经度：" + depLongitude);
        log.info("出发地纬度：" + depLatitude);
        log.info("目的地经度：" + destLongitude);
        log.info("目的地经度：" + destLatitude);

        log.info("调用地图服务，查询距离和时长");
        ForecastPriceDTO forecastPriceDTO = new ForecastPriceDTO();
        forecastPriceDTO.setDepLongitude(depLongitude);
        forecastPriceDTO.setDepLatitude(depLatitude);
        forecastPriceDTO.setDestLongitude(destLongitude);
        forecastPriceDTO.setDestLatitude(destLatitude);
        ResponseResult<DirectionResponse> direction = serviceMapClient.direction(forecastPriceDTO);

        Integer distance = direction.getData().getDistance();
        Integer duration = direction.getData().getDuration();
        log.info("距离：" + distance + ", 时长：" + duration);


        log.info("读取计价规则");
        Map<String, Object> queryMap = new HashMap<>();
        queryMap.put("city_code", "110000");
        queryMap.put("vehicle_type", "1");
        List<PriceRule> priceRules = priceRuleMapper.selectByMap(queryMap);
        if (priceRules.size() == 0) {
            return ResponseResult.fail(CommonStatusEnum.PRICE_RULE_EMPTY.getCode(), CommonStatusEnum.PRICE_RULE_EMPTY.getValue());
        }

        PriceRule priceRule = priceRules.get(0);

        log.info("根据距离、时长和计价规则，计算价格");
        double price = getPrice(distance, duration, priceRule);

        ForecastPriceResponse forecastPriceResponse = new ForecastPriceResponse();
        forecastPriceResponse.setPrice(price);
        return ResponseResult.success(forecastPriceResponse);
    }

    /**
     * 根据距离、时长及计价规则来计算预估价格
     * @param distance
     * @param duration
     * @param priceRule
     * @return
     */
    public double getPrice(Integer distance, Integer duration, PriceRule priceRule) {
        double price = 0.0;

        // 起步价
        double startFare = priceRule.getStartFare();
        price = BigDecimalUtils.add(price, startFare);

        // 里程费
        // 总里程 km
        double distanceMile = BigDecimalUtils.divide(distance, 1000);
        // 起步历程
        double startMile = (double)priceRule.getStartMile();
        double distanceSubtract = BigDecimalUtils.substract(distanceMile, startMile);
        // 最终收费的里程数 km
        double mile = Math.max(0, distanceSubtract);
        // 计程单价 元/km
        double unitPricePerMile = priceRule.getUnitPricePerMile();

        // 里程价
        double mileFare = BigDecimalUtils.multiply(mile, unitPricePerMile);
        price = BigDecimalUtils.add(price, mileFare);

        // 时长费
        // 时长的分钟数
        double timeMinute = BigDecimalUtils.divide(duration, 60);
        // 计时单价
        double unitPricePerMinute = priceRule.getUnitPricePerMinute();

        // 时长总费用
        double timeFare = BigDecimalUtils.multiply(timeMinute, unitPricePerMinute);

        price = BigDecimalUtils.add(price, timeFare);

        BigDecimal priceBigDecimal = new BigDecimal(String.valueOf(price)).setScale(2, RoundingMode.HALF_UP);
        return priceBigDecimal.doubleValue();
    }

    //public static void main(String[] args) {
    //    PriceRule priceRule = new PriceRule();
    //    priceRule.setUnitPricePerMile(1.8);
    //    priceRule.setUnitPricePerMinute(0.5);
    //    priceRule.setStartFare(10.0);
    //    priceRule.setStartMile(3);
    //    System.out.println(getPrice(6500, 1800, priceRule));
    //}
}
